﻿using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

using NinjaToolbox.SubComponentModule.Example;

namespace NinjaToolbox.BattleSystem
{
    public class DamageSubComponent : BattleObject_SubComponent<DamageSubComponent_Model>
    {
        bool mIsDied;

        public bool Alive { get { return Model.hp > 0; } }
        public int Hp { get { return Model.hp; } }
        public bool GodMode { get { return Model.godMode; } set { Model.godMode = value; } }

        /// <summary>
        /// Arg1 - Self, Arg2 - Old HP, Arg3 - New HP.
        /// </summary>
        public event Action<BattleObject, int, int> OnHPChangedCallback;
        public event Action<BattleObject> OnDiedCallback;
        public event Action<BattleObject> OnResurrectionCallback;
        /// <summary>
        /// Arg1 - self, Arg2 - New HP(in), Arg3 - New HP(out).
        /// </summary>
        public event Func<BattleObject, int, int> OnChangeHPBeforeCallback;
        /// <summary>
        /// Arg1 - Self, Arg2 - Attacker, Arg3 - damage.
        /// </summary>
        public event Action<BattleObject, BattleObject, int> OnHurtCallback;
        /// <summary>
        /// Arg1 - Self, Arg2 - Hurter.
        /// </summary>
        public event Action<BattleObject, BattleObject> OnAttackCompletedCallback;

        /// <summary>
        /// Arg1 - Self, Arg2 - Deceased.
        /// </summary>
        public event Action<BattleObject, BattleObject> OnKilledCallback;


        public void ChangeHP(int newHP)
        {
            newHP = Math.Max(newHP, 0);

            if (Model.hp == newHP) return;

            OnHPChangedCallback?.Invoke(mBattleObject, Model.hp, newHP);

            Model.hp = newHP;

            if (Model.hp <= 0 && !mIsDied)
            {
                OnDiedCallback?.Invoke(mBattleObject);

                mIsDied = true;
            }
        }

        public void Resurrection(int maxHp)
        {
            if (maxHp <= 0) return;

            Model.hp = maxHp;

            mIsDied = false;

            OnResurrectionCallback?.Invoke(mBattleObject);
        }

        protected override void SubComponent_OnEnable()
        {
            base.SubComponent_OnEnable();

            mBattleObject.OnContactOtherFactionCallback += onContactOtherFactionCallback;
        }

        protected override void SubComponent_OnDisable()
        {
            base.SubComponent_OnDisable();

            mBattleObject.OnContactOtherFactionCallback -= onContactOtherFactionCallback;
        }

        void onContactOtherFactionCallback(BattleInfoContext obj)
        {
            if (!Model.isAttackState) return;

            var anotherDamageSubComponent = obj.ContactBattleObject
                    .BattleSubComponentContainer
                    .GetSubComponent<DamageSubComponent>();

            if (anotherDamageSubComponent != null)
            {
                if (Model.toEnemyDamage <= 0) return;
                if (anotherDamageSubComponent.Model.godMode) return;

                var a = anotherDamageSubComponent.Alive;
                var newHP = anotherDamageSubComponent.Model.hp - Model.toEnemyDamage;
                if (anotherDamageSubComponent.OnChangeHPBeforeCallback != null)
                    newHP = anotherDamageSubComponent.OnChangeHPBeforeCallback(obj.ContactBattleObject, newHP);
                anotherDamageSubComponent.ChangeHP(newHP);
                var b = !anotherDamageSubComponent.Alive;

                anotherDamageSubComponent.OnHurtCallback?.Invoke(obj.ContactBattleObject, mBattleObject, Model.toEnemyDamage);

                OnAttackCompletedCallback?.Invoke(mBattleObject, obj.ContactBattleObject);
                //这里考虑到鞭尸特性，所以这两个消息不加逻辑判断。

                if (a && b)
                {
                    OnKilledCallback?.Invoke(mBattleObject, obj.ContactBattleObject);
                }
            }
        }
    }
}
